package com.gitee.wsl.data.store

import com.gitee.wsl.data.observer.DataChangedObservable
import com.gitee.wsl.io.api.ValueContainer
import com.gitee.wsl.reflect.TypeInfo
import com.gitee.wsl.reflect.typeInfo
import com.gitee.wsl.io.api.getOrNullUseDecode
import kotlinx.serialization.KSerializer
import kotlinx.serialization.json.Json
import kotlin.reflect.KClass

interface StoreServer : ValueContainer, DataChangedObservable {

    fun <T:Any> putPreference(name: String, value: T) = put(name, value)

    fun <T> getPreferenceOrNull(name: String, type: TypeInfo): T? = getOrNull(name,type.type) as T?

    fun <T: Any> getPreferenceOrNull(name: String, type:KClass<T>): T? = getPreferenceOrNull(name,TypeInfo(type))

    fun <T: Any> getPreference(name: String, type:KClass<T>): T = getPreference(name,TypeInfo(type))

    fun <T> getPreference(name: String, type: TypeInfo) :T = getPreferenceOrNull(name,type) ?: throw IllegalStateException("No instance for key $name")
    fun <T:Any> getPreferenceOrDefault(name: String,default:T): T = getPreferenceOrNull(name,default::class) ?:default

    suspend fun <T:Any> saveDataAsync(key:String, data : T) = putPreference(key, data)

    companion object
}

inline fun <reified T> StoreServer.getPreferenceOrNull(name: String) = getPreferenceOrNull<T>(name, typeInfo<T>())

inline fun <reified T> StoreServer.getPreference(name: String) = getPreference<T>(name, typeInfo<T>())

inline fun <reified T> StoreServer.getPreferenceOrNull(name: String, serializer: KSerializer<T>)
   = getOrNullUseDecode(name,serializer)


inline fun <reified T> StoreServer.putPreference(name: String, value: T, serializer: KSerializer<T>)
   = put(name, Json.encodeToString(serializer,value))


/** Equivalent to [Settings.hasKey] */
operator fun StoreServer.contains(key: String): Boolean = isExits(key)


